using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml.Linq;
using OFX.Aggregator.Infrastructure;

namespace OFX.Aggregator.Implementation.ViaVerde
{
	public class XmlStatementInterpreter : IStatementInterpreter
	{
		#region IStatementInterpreter Members

		public Statement InterpretStatement(string xml)
		{
			XDocument doc = XDocument.Load(new StringReader(xml));
			XElement statementElement = doc.Element("EXTRACTO");
			XElement clientElement = statementElement.Element("CLIENTE");
			var statement = new Statement
			                	{
			                		Currency = "EUR",
			                		Date = DateTime.Now,
			                		Account =
			                			{
			                				BankId = "Brisa, SA",
			                				Number = clientElement.Attribute("id").Value,
			                				Type = AccountType.CreditLine,
			                				Holder = clientElement.Element("NOME").Value,
			                			}
			                	};


			var creditTransactionsDictionary = new Dictionary<DateTime, double>();

			foreach (XElement identifierElement in statementElement.Elements("IDENTIFICADOR"))
			{
				var identifier = new PaymentOriginator {Id = identifierElement.Attribute("id").Value};

				foreach (XElement transactionElement in identifierElement.Elements("TRANSACCAO"))
				{
					string postedHour = transactionElement.Element("HORA").Value;
					string postedDate = transactionElement.Element("DATA").Value;
					string dateTime = string.Format("{0} {1}", postedDate, postedHour);
					DateTime datePosted = DateTime.ParseExact(dateTime, "yyyy-MM-dd HH:mm", null, DateTimeStyles.AssumeLocal);

					var statementLine = new StatementLine
					                    	{
					                    		Amount =
					                    			-double.Parse(transactionElement.Element("IMPORTANCIA").Value, NumberStyles.Currency,
					                    			              NumberFormatInfo.InvariantInfo),
					                    		DatePosted = datePosted,
					                    		TransactionType = TransactionType.POS,
					                    		TransactionId = dateTime,
					                    		Description = "Brisa, SA",
					                    		Memo =
					                    			string.Format("{0}: {1}", transactionElement.Element("TIPO").Value,
					                    			              transactionElement.Element("DESCRITIVO").Value)
					                    	};

					string valueHour = transactionElement.Element("HORA_ENTRADA").Value;
					string valueDate = transactionElement.Element("DATA_ENTRADA").Value;
					valueHour = valueHour.Trim(new[] {'-'});
					valueDate = valueDate.Trim(new[] {'-'});
					if (string.IsNullOrEmpty(valueHour))
						valueHour = postedHour;
					if (string.IsNullOrEmpty(valueDate))
						valueDate = postedDate;

					dateTime = string.Format("{0} {1}", valueDate, valueHour);
					statementLine.DateValue = DateTime.ParseExact(dateTime, "yyyy-MM-dd HH:mm", null, DateTimeStyles.AssumeLocal);

					XElement creditDateElement = transactionElement.Element("DATA_DEBITO");
					if (creditDateElement != null)
					{
						DateTime creditDate = DateTime.ParseExact(creditDateElement.Value, "yyyy-MM-dd", null, DateTimeStyles.AssumeLocal);
						double amount;

						if (creditTransactionsDictionary.TryGetValue(creditDate, out amount))
						{
							creditTransactionsDictionary[creditDate] = amount + statementLine.Amount;
						}
						else
						{
							creditTransactionsDictionary[creditDate] = statementLine.Amount;
						}
					}

					identifier.StatementLines.Add(statementLine);
				}

				statement.PaymentOriginators.Add(identifier);
			}

			var creditPaymentOriginator = new PaymentOriginator();

			foreach (var kvp in creditTransactionsDictionary)
			{
				var statementLine = new StatementLine
				                    	{
				                    		Amount = -kvp.Value,
				                    		DatePosted = kvp.Key,
				                    		TransactionType = TransactionType.Transfer,
				                    		TransactionId = string.Format("Payment:{0}", kvp.Key),
				                    		Description = "Transfer"
				                    	};

				creditPaymentOriginator.StatementLines.Add(statementLine);
			}

			statement.PaymentOriginators.Add(creditPaymentOriginator);

			StatementInterpreterHelper.InferStatementDates(statement);

			return statement;
		}

		#endregion
	}
}